//------------------------------------------------------------------------
// Abstract: Define of class BitContainer
//
// Authoring: XiaoHanxiong
//
// Time: 2014.03.31
//
// Static test:
//
// Version history:
//		Ver_1.0 : 2014.03.31	XiaoHanxiong
//------------------------------------------------------------------------
#ifndef _Library_BitContainer_h_
#define _Library_BitContainer_h_

#include "stdafx.h"
#include "Define.h"

namespace Library
{
	template<size_t _BitSize>
	class BitContainer
	{
	public:
		// Constructor
		BitContainer(){};
		// Destructor
		~BitContainer(){};

	public:
		typedef string BitName;
		typedef size_t BitPos;
		typedef size_t BitSize;
		typedef size_t BitValue;
		struct BitSchema
		{
			BitPos m_begin;
			BitPos m_end;
		};
		typedef map<BitName, BitSchema> BitContainerMap;

	protected:
		bitset<_BitSize> m_valueContainer;
		BitContainerMap m_containerMap;
		enum { _Bits = _BitSize, _BitPosInvalid = BitPos(-1) };


	public:
		bool InsertField(const string& name, BitPos& begin, BitSize bitSize);
		void DeleteField(const string& name);
		void SetValue(BitPos begin, BitPos end, BitValue value);
		bool SetValue(const string& name, BitValue value);
		void GetValue(BitPos begin, BitPos end, BitValue& value);
		bool GetValue(const string& name, BitValue& value);

		void UnSerialize(void* valuePtr, BitSize byteSize, BitPos begin = 0);
		size_t GetBeginPos(const BitName& name);
		size_t GetEndPos(const BitName& name);

		void ResetValue();
		void ClearField();
	};

	
	/*
		Implement of BitContainer
		template class usually implement in *.h
	*/
	template<size_t _BitSize>
	bool BitContainer<_BitSize>::InsertField(const string& name, BitPos& begin, BitSize bitSize)
	{
		if( m_containerMap.find(name) == m_containerMap.end() &&
			begin + bitSize <= _BitSize )
		{
			BitSchema schema;
			schema.m_begin = begin;
			schema.m_end = begin + bitSize - 1;
			m_containerMap[name] = schema;
			begin += bitSize;
			return true;
		}
		return false;
	}

	template<size_t _BitSize>
	void BitContainer<_BitSize>::DeleteField( const string& name )
	{
		m_containerMap.erase(name);
	}

	template<size_t _BitSize>
	void BitContainer<_BitSize>::SetValue(BitPos begin, BitPos end, BitValue value)
	{
		if( begin >= m_valueContainer.size() || 
			end >= m_valueContainer.size())
			return;

		for( BitSize n = begin; n <= end; n++ )
		{
			BitValue tmp_value = value & ((BitValue)1 << n);
			if(tmp_value != 0)  m_valueContainer.set(n, true);
			else  m_valueContainer.set(n, false);
		}
	}

	template<size_t _BitSize>
	bool BitContainer<_BitSize>::SetValue(const string& name, BitValue value)
	{
		BitContainerMap::iterator itr = m_containerMap.find(name);
		if( itr != m_containerMap.end() )
		{
			SetValue(itr->second.m_begin, itr->second.m_end, value);
			return true;
		}
		return false;
	}

	template<size_t _BitSize>
	bool BitContainer<_BitSize>::GetValue(const string& name, BitValue& value)
	{
		BitContainerMap::iterator itr = m_containerMap.find(name);
		if( itr != m_containerMap.end() )
		{
			GetValue(itr->second.m_begin, itr->second.m_end, value);
			return true;
		}
		return false;
	}

	template<size_t _BitSize>
	void BitContainer<_BitSize>::GetValue(BitPos begin, BitPos end, BitValue& value)
	{
		BitValue tmp_value = 0;
		BitSize bit_size = end - begin;

		for( unsigned int n = begin; n <= end; n++ )
		{
			if(m_valueContainer.at(n) == true)
				tmp_value |= (BitValue)1 << n;
		}
		value = tmp_value;
	}

	template<size_t _BitSize>
	void BitContainer<_BitSize>::UnSerialize(void* valuePtr, BitSize byteSize, BitPos begin = 0)
	{
		byte* ptr = (byte*)valuePtr;
		BitSize size = m_valueContainer.size();
		for( BitPos nbyte = 0; nbyte < byteSize && begin + nbyte < size; nbyte++ )
		{
			BitPos byte_pos = begin + nbyte;
			for( BitSize nbit = 0; nbit < 8; nbit++ )
			{
				BitValue tmp_value = ((BitValue)1 << nbit) & ptr[nbyte];
				if(tmp_value) m_valueContainer.set(byte_pos * 8 + nbit, true);
				else m_valueContainer.set(byte_pos * 8 + nbit, false);
			}
		}
	}

	template<size_t _BitSize>
	size_t BitContainer<_BitSize>::GetBeginPos( const BitName& name )
	{
		BitContainerMap::iterator itr = m_containerMap.find(name);
		if(itr != m_containerMap.end())
			return (BitPos)itr->second.m_begin;
		else return (BitPos)_BitPosInvalid;
	}

	template<size_t _BitSize>
	size_t BitContainer<_BitSize>::GetEndPos( const BitName& name )
	{
		BitContainerMap::iterator itr = m_containerMap.find(name);
		if(itr != m_containerMap.end())
			return (BitPos)itr->second.m_end;
		else return (BitPos)_BitPosInvalid;
	}

	template<size_t _BitSize>
	void BitContainer<_BitSize>::ResetValue()
	{
		m_valueContainer.reset();
	}

	template<size_t _BitSize>
	void BitContainer<_BitSize>::ClearField()
	{
		m_containerMap.clear();
		m_valueContainer.reset();
	}

}// _Library

#endif